package edu.hawaii.teams.halealohacli.command;

import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import javax.xml.datatype.XMLGregorianCalendar;
import org.wattdepot.client.BadXmlException;
import org.wattdepot.client.MiscClientException;
import org.wattdepot.client.NotAuthorizedException;
import org.wattdepot.client.ResourceNotFoundException;
import org.wattdepot.client.WattDepotClient;

/**
 * Prints a timestamp and the current power for the source every interval.
 * 
 * @author Rylan Kwock
 * 
 */
public class MonitorPower implements Command {

  /**
   * Print a timestamp and the current power for the source at a user-defined interval of seconds.
   * If no interval is provided, the command defaults to an interval of 10 seconds. When any
   * character is entered after the command has been executed, the monitoring process stops and the
   * user returns to the command loop.
   * 
   * Command should be formatted as "monitor-power [source] [interval]"
   * 
   * @param client A WattDepotClient to find the source in.
   * @param details String instances identifying the source and interval to examine.
   * @return data A String containing the energy that the source has consumed during a given
   * interval. For each new interval, places each on a new line.
   * @throws Exception Handles any problems that may occur.
   * 
   */
  @Override
  public String getData(final WattDepotClient client, final String... details) throws Exception {
    // Constant double used to convert from watt to kilowatt.
    final double KILO = 1000.0;
    final StringBuilder buffer = new StringBuilder();
    String currentSource = null;
    String givenInterval = null;
    long interval = 10000;

    for (String text : details) {
      // If currentSource is null, then this String is a source
      if (currentSource == null) {
        currentSource = text;
      }
      // Else if givenDate is null, then this String is an interval
      else if (givenInterval == null && (text != null)) {
        givenInterval = text;
        interval = 1000 * (Long.parseLong(givenInterval));
      }

      // If both currentSource and givenInterval are defined
      if ((currentSource != null) && (givenInterval != null)) {
        try {
          /**
           * Creates new timer task to be executed at each interval. Will use the
           * getLatestPowerConsumed method as the "task".
           */
          TimerTask task = new TimerTask() {
            /**
             * Retrieves the latest power from the current source.
             */
            @Override
            public void run() {
              try {
                double power = client.getLatestPowerConsumed(details[0]) / KILO;
                buffer.append("The current power consumption is: " +
                    String.format("%.1f", power) + " kW\n");
              }
              catch (NotAuthorizedException e) {
                buffer.append("Error: You are not authorized to retrieve the data.\n\n");
              }
              catch (IllegalArgumentException e) {
                buffer.append("Error: An error occurred in using the XMLGregorianCalendar " +
                    "class.\n\n");
              }
              catch (BadXmlException e) {
                buffer.append("Error: An error occurred in the XML from the server.\n\n");
              }
              catch (MiscClientException e) {
                buffer.append("Error: An error occurred while retrieving data.\n\n");
              }
              catch (ResourceNotFoundException e) {
                buffer.append("Error: The source could not be found.\n\n");
              }
            }
          };

          // Create XMLGregorianCalendar to retrieve the current time and date.
          XMLGregorianCalendar timeNow = client.getLatestSensorData(currentSource).getTimestamp();
          Date startTime = timeNow.toGregorianCalendar().getTime();
          
          Timer clock = new Timer();
          clock.schedule(task, startTime, interval);
          Thread.sleep(interval);
          
          // Terminates the timer
          clock.cancel();
        }
        catch (NumberFormatException e) {
          buffer.append("Error: An error occurred while parsing the date.\n\n");
        }
        catch (StringIndexOutOfBoundsException e) {
          buffer.append("Error: An error occurred while parsing the date; "
              + "the formatting is incorrect.\n\n");
        }
        catch (IllegalArgumentException e) {
          buffer.append("Error: An error occurred in using the XMLGregorianCalendar class.\n\n");
        }
        catch (BadXmlException e) {
          buffer.append("Error: An error occurred in the XML from the server.\n\n");
        }
        catch (MiscClientException e) {
          buffer.append("Error: An error occurred while retrieving data.\n\n");
        }
        catch (ResourceNotFoundException e) {
          buffer.append("Error: The source " + currentSource + " could not be found.\n\n");
        }

        // Reset currentSource and givenInterval to null
        currentSource = null;
        givenInterval = null;
      }
    }
    return buffer.toString();
  }
}